﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
using ApartmentBillsManager.Start.Annotations;
using ApartmentBillsManager.Start.Common;

namespace ApartmentBillsManager.Start.Services
{
    class CreateEditBill : INotifyPropertyChanged
    {
        #region Data Members
        private ObservableCollection<Roommate> _roommates;
        private decimal _amount;
        private DateTime _endDate;
        private Roommate _paid;
        private MessageBoxResult _messageBoxResult;
        private DateTime _startDate;
        private string _remark;

        #endregion

        #region Properties
        public bool CanAddBill
        {
            get
            {
                if (Paid == null)
                    return false;

                if (EndDate < StartDate)
                    return false;

                if (Amount.Equals(0))
                    return false;

                return true;
            }
        }

        public ObservableCollection<Roommate> Roommates
        {
            get { return _roommates; }
            private set
            {
                _roommates = value;
                OnPropertyChanged("Roommates");
            }
        }

        public Roommate Paid
        {
            get { return _paid; }
            set
            {
                _paid = value;
                OnPropertyChanged("Paid");
                OnPropertyChanged("CanAddBill");
            }
        }

        public DateTime DatePaid { get; set; }

        public BillCategory Category { get; set; }

        public decimal Amount
        {
            get { return _amount; }
            set
            {
                _amount = value;
                OnPropertyChanged("TotalDays");
                OnPropertyChanged("CanAddBill");
            }
        }

        public DateTime StartDate
        {
            get { return _startDate.Date; }
            set
            {
                _startDate = value;
                OnPropertyChanged("TotalDays");
                OnPropertyChanged("CanAddBill");
            }
        }

        public DateTime EndDate
        {
            get { return _endDate.Date; }
            set
            {
                _endDate = value;
                OnPropertyChanged("TotalDays");
                OnPropertyChanged("CanAddBill");
            }
        }

        public int TotalDays
        {
            get { return EndDate.Subtract(StartDate).Days + 1; }
        }

        public string Remark
        {
            get { return _remark; }
            set
            {
                _remark = value;
                OnPropertyChanged("Remark");
            }
        }

        #endregion

        #region Public Methods
        public Bill CreateNewBill(ObservableCollection<Roommate> roommates)
        {
            Roommates = roommates;

            Paid = null;
            Amount = 0;
            Category = BillCategory.Electricity;
            DatePaid = DateTime.Now;
            StartDate = DateTime.Now;
            EndDate = DateTime.Now.AddDays(1);
            Remark = string.Empty;

            OpenWindow();

            return _messageBoxResult == MessageBoxResult.OK ? new Bill(Category, Amount, StartDate, EndDate, Paid, DatePaid, Remark) : null;
        }

        public Bill EditExistingBill(Bill bill, ObservableCollection<Roommate> roommates)
        {
            Roommates = roommates;

            Paid = roommates.First(x => x.Name == bill.Paid.Name);
            DatePaid = bill.DatePaid;
            Category = bill.Category;
            Amount = bill.Amount;
            StartDate = bill.StartDate;
            EndDate = bill.EndDate;
            Remark = bill.Remark;

            OpenWindow();

            return _messageBoxResult == MessageBoxResult.OK ? new Bill(Category, Amount, StartDate, EndDate, Paid, DatePaid, Remark) : null;
        }
        #endregion

        #region Private Methods
        private void OpenWindow()
        {
            var createNewBillWindow = new Window
                {
                    Content = this,
                    Title = "Create New Bill",
                    SizeToContent = SizeToContent.WidthAndHeight
                };

            createNewBillWindow.ShowDialog();
        }

        private void CreateBillButton(object obj)
        {
            _messageBoxResult = MessageBoxResult.OK;

            CloseWindow();
        }

        private void CancelBillButton(object obj)
        {
            _messageBoxResult = MessageBoxResult.Cancel;

            CloseWindow();
        }

        private void CloseWindow()
        {
            Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive).Close();
        }
        #endregion

        #region Commands
        public ICommand CreateBillButtonCommand
        {
            get { return new DelegateCommand(CreateBillButton); }
        }

        public ICommand CancelBillButtonCommand
        {
            get { return new DelegateCommand(CancelBillButton); }
        }
        #endregion

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
